from django.http import HttpResponse
from django.utils import simplejson
from django.core.mail import mail_admins
from django.utils.translation import ugettext as _
from django.db import models
from django.core.serializers.json import DjangoJSONEncoder
import sys, datetime

def json_view(func):
    def wrap(request, *a, **kw):
        response = None
        try:
            response = func(request, *a, **kw)
            try:
                response = response.__dict__
            except:
                response = dict(response)
            for k,v in response.items():
                if isinstance(v, datetime.date) or isinstance(v, datetime.datetime):
                    response[k] = str(v)
            if 'result' not in response:
                response['result'] = 'ok'
        except Exception, e:
            # Mail the admins with the error
            exc_info = sys.exc_info()
            subject = 'JSON view error: %s' % request.path
            try:
                request_repr = repr(request)
            except:
                request_repr = 'Request repr() unavailable'
            import traceback
            message = 'Traceback:\n%s\n\nRequest:\n%s' % (
                '\n'.join(traceback.format_exception(*exc_info)),
                request_repr,
                )
            #mail_admins(subject, message, fail_silently=True)

            # Come what may, we're returning JSON.
            if hasattr(e, 'message'):
                msg = e.message
            else:
                msg = _('Internal error')+': '+str(e)
            response = {'result': 'error',
                        'text': msg}
        json = simplejson.dumps(response)
        return HttpResponse(json, mimetype='text/plain')
    return wrap

class JSONField(models.TextField):
    """JSONField is a generic textfield that neatly serializes/unserializes
    JSON objects seamlessly"""
 
    # Used so to_python() is called
    __metaclass__ = models.SubfieldBase
 
    def to_python(self, value):
        """Convert our string value to JSON after we load it from the DB"""
 
        if value == "":
            return None
 
        if isinstance(value, basestring):
            return simplejson.loads(value)
 
        return value
 
    def get_db_prep_save(self, value):
        """Convert our JSON object to a string before we save"""
 
        if value == "":
            return None
 
        if isinstance(value, dict):
            return simplejson.dumps(value, cls=DjangoJSONEncoder)
 
        return super(JSONField, self).get_db_prep_save(value)
